#include "canvas.h"
#include "ui_canvas.h"
#include <QPainter>
#include <QDebug>
#include <QMouseEvent>

Canvas::Canvas(QWidget *parent) :
    QWidget(parent), ui(new Ui::Canvas),
    viewPort(QRect(QPoint(-5,-5), QPoint(5,5)))
{
    ui->setupUi(this);

    m_buffer = QImage(QSize(50,50), QImage::Format_RGB32);
    QPainter p;
    p.begin(&m_buffer);
    p.fillRect(m_buffer.rect(),Qt::white);
    p.end();
}

Canvas::~Canvas()
{
    delete ui;
}

void Canvas::resizeEvent(QResizeEvent *)
{
    setupBuffer();
    emit draw();
}

void Canvas::clear()
{
    QPainter p;
    p.begin(&m_buffer);
    p.fillRect(m_buffer.rect(),Qt::white);
    p.end();

    paintBuffer();
}

void Canvas::setupBuffer()
{
    m_buffer = QImage(ui->imageContainer->size(), QImage::Format_RGB32);
    QPainter p;
    p.begin(&m_buffer);
    p.fillRect(m_buffer.rect(),Qt::white);
    p.end();

    paintBuffer();
}

void Canvas::paintBuffer()
{
    ui->imageContainer->setPixmap(QPixmap::fromImage(m_buffer));
}

void Canvas::setViewPort(const QRect& vp)
{
    viewPort = vp;
}

QPoint Canvas::worldToSreen(const QVector2D& v)
{
    float xwmax, xwmin, ywmax, ywmin;
    float xmax, ymax;

    xmax = m_buffer.width()-1;
    ymax = m_buffer.height()-1;

    xwmin = viewPort.left();
    xwmax = viewPort.right();
    ywmin = viewPort.top();
    ywmax = viewPort.bottom();

    double x = xmax*(v.x() - xwmin)/(xwmax - xwmin);
    double y = ymax*(v.y() - ywmin)/(ywmax - ywmin);

    QPoint p(qRound(x), qRound(y));
    p.setY(ymax - p.y());
    return p;
}

QVector2D Canvas::screenToWorld(const QPoint& p)
{
    float xwmax, xwmin, ywmax, ywmin;
    float xmax, ymax;

    xmax = m_buffer.width()-1;
    ymax = m_buffer.height()-1;

    xwmin = viewPort.left();
    xwmax = viewPort.right();
    ywmin = viewPort.top();
    ywmax = viewPort.bottom();

    float inx = p.x();
    float iny = ymax - p.y();

    double x = xwmin + inx*(xwmax- xwmin)/xmax;
    double y = ywmin + iny*(ywmax- ywmin)/ymax;

    return QVector2D(x,y);
}

void Canvas::drawLines(const QVector<QVector2D>& points)
{
    QVector<QPoint> screenPoints;

    for(int i = 0; i < points.size(); ++i)
        screenPoints.append(worldToSreen(points[i]));

    QPainter p;
    p.begin(&m_buffer);
    for(int i = 0; i < screenPoints.size()-1; ++i )
        p.drawLine(screenPoints[i],screenPoints[i+1]);
    p.end();

    paintBuffer();
}

void Canvas::drawPoints(const QVector<QVector2D>& points)
{
    QVector<QPoint> screenPoints;

    for(int i = 0; i < points.size(); ++i)
        screenPoints.append(worldToSreen(points[i]));

    QPainter p;
    p.begin(&m_buffer);
    for(int i = 0; i < screenPoints.size(); ++i )
        p.drawPoint(screenPoints[i]);
    p.end();

    paintBuffer();
}

void Canvas::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        QPoint p = ui->imageContainer->mapFromGlobal(event->globalPos());
        if(m_buffer.valid(p))
        {
            emit leftPressed(screenToWorld(p));
        }
    }
}

void Canvas::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        QPoint p = ui->imageContainer->mapFromGlobal(event->globalPos());
        if(m_buffer.valid(p))
        {
            emit leftReleased(screenToWorld(p));
        }
    }
}
